home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / TestMain.cp < prev   
Encoding:
Text File  |  1996-02-19  |  9.2 KB  |  361 lines  |  [TEXT/CWIE]

  1. #include "Exceptions.h"
  2. #include "DatabaseDocument.h"
  3. #include "DBRecord.h"
  4. #include "DBElement.h"
  5. #include "DBProperty.h"
  6. #include "DataRecord.h"
  7. #include "ReferenceTemplates.h"
  8.  
  9. #include "Application.h"
  10. #include "ScriptableDBDocument.h"
  11. #include "HFSBackingStore.h"
  12.  
  13. //
  14. // For MarkTokenMergeProc
  15. //
  16. #include "MarkToken.h"
  17.  
  18. #include "MoreAEM.h"
  19. #include "ResolveObjectSpecifier.h"
  20. #include "Accessor.h"
  21. #include "CoreSuite.h"
  22. #include "TransactionSuite.h"
  23. #include "PseudoRandom.h"
  24.  
  25. #include <Events.h>
  26. #include <Gestalt.h>
  27.  
  28.  
  29. #include "Futures.h"
  30. #include "ThreadContext.h"
  31. #include <Threads.h>
  32.  
  33. //
  34. // Initialization stuff
  35. //
  36. #include "Fonts.h"
  37. #include "Windows.h"
  38. #include "Menus.h"
  39. #include "TextEdit.h"
  40. #include "Dialogs.h"
  41.  
  42.  
  43. #include "EventHandlerTable.h"
  44.  
  45. class TApplication;
  46.  
  47. void MainLoop(TEventHandlerTable& eventTable);
  48. void InitAll();
  49.  
  50. TTokenDescriptor MakeNullContainer();
  51.  
  52. Boolean gApplicationRunning = false;
  53.  
  54. pascal OSErr QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon);
  55.  
  56.  
  57. Boolean            gHasAppleEvents;
  58.  
  59.  
  60. void InstallStringCompareBehavior();
  61.  
  62.  
  63. //--------------------------------------------------------------------------------
  64. // main
  65. //--------------------------------------------------------------------------------
  66. main()
  67. {
  68.     TEventHandlerTable eventTable;
  69.     OSErr err = noErr;
  70.     
  71.     //
  72.     // Make the universe come alive
  73.     //
  74.     InitAll();
  75.  
  76.     //
  77.     // Before any threads are created, make sure that the main thread
  78.     // gets swap in and swap out context switch messages
  79.     //
  80.     ThreadCreateNotifyHandler(kApplicationThreadID, 0);
  81.  
  82.     //
  83.     // Use a different set of random numbers
  84.     // every time
  85.     //
  86.     SetRandomSeed(TickCount());
  87.     
  88. #if 1
  89.     Try
  90.     {
  91.         // DebugStr("\pset up try");
  92.         
  93.         FailErr(-42);
  94.         
  95.         DebugStr("\pcame back after throw?");
  96.     }
  97.     Catch(err)
  98.     {
  99.         //if(err == -42)
  100.         //    DebugStr("\pcaught the exception");
  101.         //else
  102.         //    DebugStr("\pwrong value?");
  103.     }
  104.     
  105.     // DebugStr("\pcontinue with life");
  106. #endif
  107.  
  108.     Try
  109.     {
  110.         //
  111.         // Insure that gApplication is initialized
  112.         //
  113.         TApplication::Instance();
  114.  
  115.         TDescriptor::SetCallbackFlags(kAEIDoWhose | kAEIDoMarking);
  116.         InstallStringCompareBehavior();
  117.         InstallNullContainerCreationProc(MakeNullContainer);
  118.         InstallPreResolveProc(ResolveObjectSpecifier);
  119.         InstallMergeTokensProc(MarkTokenMergeProc);
  120.         TAccessor::InstallAEHandlers();
  121.  
  122.         //
  123.         // Install our event handlers into our main event-handler table
  124.         //
  125.         eventTable.InstallHandler(kCoreEventClass, kAEQuitApplication, (EventHandlerProcPtr) &QuitApplicationEvent, 0);
  126.         TCoreSuite::InstallAEHandlers(eventTable);
  127.         TTransactionSuite::InstallAEHandlers(eventTable);
  128.         
  129.         //
  130.         // MainLoop will not return until gApplicationRunning goes false
  131.         //
  132.         gApplicationRunning = true;
  133.         MainLoop(eventTable);
  134.     }
  135.     Catch(err)
  136.     {
  137.         if(err != userCanceledErr)
  138.             DebugStr("\pCaught an error in testmain");
  139.     }
  140.     
  141.     //
  142.     // Before we bail out, we should save all of our documents
  143.     //
  144.     TApplication::Instance()->TearDownApplication();
  145.     
  146.     return 0;
  147. }
  148.  
  149. #define kDBSleep (60*60)
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // MainLoop: 
  153. //----------------------------------------------------------------------------------------
  154. void MainLoop(TEventHandlerTable& eventTable)
  155. {
  156.     OSErr err = noErr;
  157.  
  158.     while(gApplicationRunning == true)
  159.     {
  160.         Try
  161.         {            
  162.             unsigned long lastWNECallTick = 0;
  163.  
  164.             //
  165.             // Active threads includes the main thread.  If there
  166.             // are no active threads, then call WNE all the time.
  167.             // If there are active threads, let them run for
  168.             // at least 10 ticks before calling WNE.
  169.             //
  170.             // If we had a real scheduler, then the scheduler should
  171.             // ask the threads how busy they are; if there's a lot
  172.             // of work to be done, then the throttle should be high
  173.             // (10 or 20 ticks).  If there are threads running but they
  174.             // aren't doing anything too important, then the throttle
  175.             // could be much lower.  (The throttle could just be the
  176.             // max of what any thread said it wanted.)
  177.             //
  178.             Boolean threadsActive = TThreadContext::ActiveThreads() > 1;
  179.             unsigned long throttleWNETicks = threadsActive ? 10 : 0;
  180.             
  181.             if((TickCount() - lastWNECallTick) > throttleWNETicks)
  182.             {
  183.                 //
  184.                 // Similarly, if there are threads active, we don't want
  185.                 // to sleep for any longer than necessary (don't use zero,
  186.                 // because that value is special); note that it's unlikely
  187.                 // that WNE will actually come back in one tick.
  188.                 //
  189.                 // If there are no active threads, then sleep for a "long"
  190.                 // time.
  191.                 //
  192.                 // Again, if we had a scheduler it should ask each thread
  193.                 // how long it thought the sleep time should be, and take
  194.                 // the minimum returned by any thread.  For the most part,
  195.                 // threads that want a high throttle also want a low sleep
  196.                 // time.  However, an idle (or mostly inactive) thread might
  197.                 // want a low throttle for the time being, but might also
  198.                 // desire a low sleep time because it needs to do periodic
  199.                 // tasks every N ticks, or it's about to wake up, or...
  200.                 //
  201.                 long sleepTimeForWNE = threadsActive ? 1 : kDBSleep;
  202.                             
  203.                 //
  204.                 // Remember the tickcount that we called WaitNextEvent
  205.                 // at _after_ WNE returns (since we never know how long
  206.                 // our clients will hog the CPU for)
  207.                 //
  208.                 eventTable.Receive(kAEReceiveOneEvent, sleepTimeForWNE);
  209.                 lastWNECallTick = TickCount();
  210.             }
  211.             
  212.             //
  213.             // Idle our application and allow other threads to run.
  214.             //
  215.             YieldToAnyThread();
  216.             TApplication::Instance()->Idle();
  217.         }
  218.         Catch(err)
  219.         {
  220.             //
  221.             // For now, only pass along user canceled errors
  222.             // (n.b. Errors are not thrown through AEProcessAppleEvent,
  223.             // so it is unlikely that we will ever get here)
  224.             //
  225.             if(err == userCanceledErr)
  226.                 {
  227.                 gApplicationRunning = false;
  228.                 Throw(err);
  229.                 }
  230.             
  231.             DebugStr("\pOh no, an uncaught main-loop failure!");
  232.         }
  233.     }
  234. } // MainLoop
  235.  
  236. //----------------------------------------------------------------------------------------
  237. // QuitApplicationEvent: 
  238. //----------------------------------------------------------------------------------------
  239. pascal OSErr QuitApplicationEvent(TAEvent& /*ae*/, TAEvent& /*reply*/, long /*refCon*/)
  240. {
  241.     //
  242.     // You should never call ExitToShell from an AppleEvent handler
  243.     //
  244.     gApplicationRunning = false;
  245.     
  246.     return noErr;
  247. } // QuitApplicationEvent
  248.  
  249.  
  250. //----------------------------------------------------------------------------------------
  251. // InitAll
  252. // 
  253. // Initialize all of the relivant Macintosh managers.  We probably
  254. // don't need to do _all_ of this for db+.
  255. //----------------------------------------------------------------------------------------
  256. void InitAll()
  257. {
  258.     long    heapSpace;
  259.     Ptr        appLimit;
  260.     THz        appBase;
  261.     short    callsToMoreMasters = 10;
  262.     
  263.     appBase = ApplicZone();
  264.     appLimit = GetApplLimit();
  265.     heapSpace = FreeMem();
  266.     MaxApplZone();
  267.     appLimit = GetApplLimit();
  268.     heapSpace = FreeMem();
  269.     while( callsToMoreMasters-- )
  270.         MoreMasters();
  271.     
  272.     InitGraf(&qd.thePort);
  273.     InitFonts();
  274.     FlushEvents(everyEvent, 0);
  275.     InitWindows();
  276.     InitMenus();
  277.     TEInit();
  278.     InitDialogs(0);
  279.  
  280.     //
  281.     // Initialize the Object Support Library
  282.     // and install the futures package.
  283.     //
  284.     AEObjectInit();
  285.     InitFutures(ThreadCreateHandler);
  286.     
  287. #if 0
  288.     long    gestaltResult;
  289.     //
  290.     // Get the SysEnvirons record
  291.     //
  292.     SysEnvirons( 1, &gThisMacintosh );
  293.  
  294.     //
  295.     // Check to see if AppleEvents are available (we are going to REQUIRE them)
  296.     //
  297.     OSErr theErr = Gestalt( gestaltAppleEventsAttr, &gestaltResult );
  298.     gHasAppleEvents = ( (theErr == noErr) && ((gestaltResult & (1L << gestaltAppleEventsPresent)) != 0) );
  299. #endif
  300. } // InitAll
  301.  
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // MakeNullContainer: 
  305. //----------------------------------------------------------------------------------------
  306. TTokenDescriptor MakeNullContainer()
  307. {
  308.     TTokenDescriptor nullContainerDesc;
  309.     
  310.     nullContainerDesc.AdoptToken(TApplication::Instance());
  311.     
  312.     return nullContainerDesc;
  313. } // MakeNullContainer 
  314.  
  315. #if 0
  316.  
  317. //----------------------------------------------------------------------------------------
  318. // Global operator new
  319. //----------------------------------------------------------------------------------------
  320. void* operator new(size_t size)
  321. {
  322. }
  323.  
  324. //----------------------------------------------------------------------------------------
  325. // Global operator delete
  326. //----------------------------------------------------------------------------------------
  327. void operator delete(void* object, size_t size)
  328. {
  329.  
  330. }
  331.  
  332. #endif
  333.  
  334. //    From UException.cp:
  335. //
  336. //    The C++ draft standard states that the Exception Handling mechanism
  337. //    call terminate() when encountering certain unrecoverable errors,
  338. //    such as:
  339. //        - Not finding a handler for a thrown exception
  340. //        - Finding a corrupted stack
  341. //        - A destructor called during stack unwinding tries to exit
  342. //            using an exception
  343. //
  344. //    The default implementation of terminate() calls abort().
  345. //
  346. //    abort() is a standard ANSI C library function. Since PowerPlant
  347. //    programs frequently don't include the ANSI C library, the abort()
  348. //    function is defined below.
  349. //
  350. //    Do NOT include this file in your project if you use the ANSI C library.
  351. //    If you use the ANSI C Library, include the file console.stubs.c (in the
  352. //    folder with the SIOUX libraries) in your project instead of UException.cp.
  353.  
  354. extern "C" void abort(void);
  355. void abort(void)
  356. {
  357.     DebugStr("\pAborting Program due to uncaught exception.  Try recompiling TestMain.cp and run again (MW bug?)");
  358.  
  359.     ::ExitToShell();
  360. }
  361.